package cn.maihe.elg.operation.centers.epoint.handler.service;

import cn.maihe.elg.operation.centers.epoint.config.EpointCenterInfosConfig;
import cn.maihe.elg.operation.centers.epoint.dto.EpointBaseRespDTO;
import cn.maihe.elg.operation.centers.epoint.dto.handler.EpointGuaranteeClaimSettlementReq;
import cn.maihe.elg.operation.centers.epoint.exception.EpointException;
import cn.maihe.elg.operation.centers.epoint.handler.EpointCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.enums.*;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.ApplyOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderAttachmentDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderInfoDO;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.ApplyOrderInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderInfoService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Date;
import java.util.List;

/**
 * @Description 理赔通知接口 已开函状态才能受理理赔，理赔完成后状态置为完成，理赔状态置为1
 * @Author caixh
 * @Date 2021/7/13.
 */
@CenterTradeService(
        provider = CenterProviderEnum.EPOINT,
        centerNo = CenterNoEnum.NANPING,
        tradeType = TradeType.claimsnotice,
        reqClass = EpointGuaranteeClaimSettlementReq.class,
        respClass = EpointBaseRespDTO.class
)
@Slf4j
public class NPEpointClaimsNoticeService extends EpointCenterTradeService<EpointGuaranteeClaimSettlementReq, EpointBaseRespDTO> {
    public NPEpointClaimsNoticeService(EpointCenterInfosConfig centerInfosConfig) {
        super(centerInfosConfig);
    }

    @Resource
    ApplyOrderInfoService applyOrderInfoService;
    @Resource
    AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    RefundOrderInfoService refundOrderInfoService;
    @Resource
    private ElgResourceService elgResourceService;


    @Override
    protected void verifyParam(CenterTradeContext<EpointGuaranteeClaimSettlementReq, EpointBaseRespDTO> context) {
        super.verifyParam(context);
        EpointGuaranteeClaimSettlementReq req = context.getReq();
        String orderNo = req.getApplyno();
        Assert.notNull(orderNo, () -> "业务流水号不能为空");
        Assert.notNull(req.getBaohanno(), () -> "保函编号不能为空");
        Assert.notNull(req.getApplyusername(), () -> "理赔联系人不能为空");
        Assert.notNull(req.getApplyuserphone(), () -> "理赔联系人电话不能为空");

    }

    /**
     * 具体业务处理
     *
     * @param context
     */
    @Override
    public EpointBaseRespDTO processService(CenterTradeContext<EpointGuaranteeClaimSettlementReq, EpointBaseRespDTO> context) {

        EpointGuaranteeClaimSettlementReq req = context.getReq();
        //实际传值与applyNo一致
        String guaranteeNo = req.getBaohanno();
        String centerOrderId = req.getApplyno();

        //查询申请保函记录及状态是否已出函状态
//        AcceptOrderInfoDO orderInfo = acceptOrderInfoService.getByGuaranteeNo(guaranteeNo);
//        ApplyOrderInfoDO applyOrderInfo = applyOrderInfoService.getByGuaranteeNo(guaranteeNo);

        AcceptOrderInfoDO orderInfo = acceptOrderInfoService.getByCenterOrderId(context.getCenterId(),context.getOrgId(),centerOrderId);
        ApplyOrderInfoDO applyOrderInfo = applyOrderInfoService.getByCenterOrderId(centerOrderId);
        Assert.notNull(orderInfo, "查无此保函编号申请记录");
        Assert.notNull(applyOrderInfo, "查无此保函编号申请记录");
        Assert.isTrue(AcceptOrderStatus.HAS_OUT_GUARANTEE.getStatus() == orderInfo.getStatus(), "此保函非出函状态不能申请理赔");

        ClaimsStatus claimsStatus = ClaimsStatus.resolve(orderInfo.getClaimsStatus());
        if (claimsStatus == ClaimsStatus.SUCCESS || claimsStatus == ClaimsStatus.FAILURE) {
            throw EpointException.error("理赔处理完成[" + claimsStatus + "]," + orderInfo.getClaimsRemark());
        }
        if (claimsStatus == ClaimsStatus.PROCESSING) {
            throw EpointException.error("理赔处理中,不能重复发起理赔");
        }


//配合后管进行 审核操作，审核操作中需要同步到 accepInfo中的理赔最终状态
        RefundOrderInfoDO curDo = RefundOrderInfoDO.builder()
                .id(IdGenerate.getId()).centerId(context.getCenterId())
                .orgId(context.getOrgId()).guaranteeNo(req.getBaohanno())
                .centerOrderId(orderInfo.getCenterOrderId()).acceptOrderNo(orderInfo.getAcceptOrderNo())
                .applyOrderNo(orderInfo.getApplyOrderNo()).refundOrderNo(req.getApplyno())
                .guaranteeType(orderInfo.getGuaranteeType()).guaranteeCategory(orderInfo.getGuaranteeCategory())
                .guaranteeFee(orderInfo.getGuaranteeFee()).projectId(orderInfo.getProjectId()).projectName(orderInfo.getProjectName())
                .sectionName(orderInfo.getSectionName())
                .bidCustomerId(orderInfo.getBidCustomerId()).bidCustomerName(orderInfo.getBidCustomerName())
                .bidIndate(orderInfo.getBidIndate())
                .bidBond(applyOrderInfo.getBidBond()).refundAmount(StringUtils.isNotBlank(req.getPayeramount())? String.valueOf(StringUtil.yuanToFen(req.getPayeramount())):null)
                .institutionId(orderInfo.getInstitutionId()).institutionName(applyOrderInfo.getInstitutionName())
                .attachmentId(orderInfo.getAttachmentId()).remark(req.getReason())
                .inviteCode(orderInfo.getInviteCode())
                .applyUserName(req.getApplyusername()).applyUserPhone(req.getApplyuserphone())
                .payerAccount(req.getPayeraccount()).payerAmount(req.getPayeramount())
                .fileList(req.getFilelist())
                .gmtCreate(Date.from(Instant.now())).gmtModified(Date.from(Instant.now())).userCreate("接口申请")
                .status(RefundOrderStatus.UNREFUND.getStatus())
                .build();

        List<RefundOrderAttachmentDO> refundOrderAttachmentDOS = Lists.newArrayList();
        if (StringUtils.isNotEmpty(req.getFilelist())) {
            JSONArray fileList = JSON.parseArray(req.getFilelist());
            for (int idx = 0; idx < fileList.size(); idx++) {
                JSONObject file = fileList.getJSONObject(idx);
                try {
                    Path tmpPath = elgResourceService.downloadByURL(file.getString("fileurl"));
                    String fileType = elgResourceService.getFileType(tmpPath);
                    String fileName = "理赔-" + tmpPath.getFileName().toString();
                    String filePath = elgResourceService.transferAndSaveFile(tmpPath, "ofd", curDo.getAcceptOrderNo(), fileName);
                    String fileMd5 = elgResourceService.getFileMD5AsHex(elgResourceService.getAbsolutePath(filePath));
                    RefundOrderAttachmentDO refundOrderAttachmentDO = RefundOrderAttachmentDO.builder()
                            .refundOrderId(curDo.getId())
                            .no(idx)
                            .fileUrl(file.getString("fileurl"))
                            .filePath(filePath)
                            .fileType(fileType)
                            .fileName(fileName)
                            .fileMd5(fileMd5)
                            .gmtCreate(Date.from(Instant.now()))
                            .gmtModified(Date.from(Instant.now()))
                            .build();
                    refundOrderAttachmentDOS.add(refundOrderAttachmentDO);
                } catch (Exception e) {
                    curDo.setRemark(StringUtils.truncate(e.getMessage(), 100));
                    ElgLogger.error(log, log -> log.error("构造理赔文件对象异常:{}", e.getMessage(), e));
                }
            }
        }
        refundOrderInfoService.saveOrder(curDo, refundOrderAttachmentDOS);


        AcceptOrderInfoDO updateOrderInfo = AcceptOrderInfoDO.builder().id(orderInfo.getId())
                .claimsStatus(ClaimsStatus.PROCESSING.getStatus())
                .claimsRemark("理赔原因" + req.getReason())
                .build();
        acceptOrderInfoService.updateById(updateOrderInfo);

        return EpointBaseRespDTO.success("理赔申请已受理");
    }
}
